#include <iostream>
using namespace std;

/*
    引入多态
    1.请你封装一个函数，该函数可以展示各种动物吃东西的行为
    问题1: 形参具有通用性--》 兼容所有动物
    答案: C++规定，父类的指针或者父类的引用作为函数的形参具有兼容性，可以兼容父类本身以及派生出来的任何子类对象
    问题2: 函数内部如何区分不同子类对象
    答案: 使用C++提供的语法规则--》 虚函数

    多态：同一个方法在父类和子类中具备不同的表现形式，传递不同子类可以使用不同子类的同名方法--》叫做多态

    多态的特点和要求
      第一：必须要有继承，没有继承，就没有多态(父类的指针/引用可以指向不同的子类对象)
      第二：子类必须要重写父类的同名方法
      第三：父类的同名方法必须定义成虚函数
      注意：父类的同名方法定义成了虚函数，所有子类中同名的方法全部都默认是虚函数(子类加不加virtual都行)
*/

class Animal
{
public:
    void eat()
    {
        cout << "animal eat" << endl;
    }
};

class Dog : public Animal
{
public:
    void eat()
    {
        cout << "dog eat" << endl;
    }
};

class Cat : public Animal
{
public:
    void eat()
    {
        cout << "cat eat" << endl;
    }
};

class Sheep : public Animal
{
public:
    void eat()
    {
        cout << "sheep eat" << endl;
    }
};

class Pig : public Animal
{
public:
    void eat()
    {
        cout << "pig eat" << endl;
    }
};

// 封装函数，展示各种动物吃东西的行为
void showAnimalEat(Animal &animal)
{
    animal.eat();
}

// void showAnimalEat(Animal *animal)
// {
//     animal->eat();
// }

// void showAnimalEat(Animal animal) // 只有引用和指针的形参才具有多态性
// {
//     animal.eat();
// }

int main()
{
    Animal animal;
    Dog dog;
    Cat cat;
    Sheep sheep;
    Pig pig;

    showAnimalEat(animal);
    showAnimalEat(dog);
    showAnimalEat(cat);
    showAnimalEat(sheep);
    showAnimalEat(pig);

    // showAnimalEat(&animal);
    // showAnimalEat(&dog);
    // showAnimalEat(&cat);
    // showAnimalEat(&sheep);
    // showAnimalEat(&pig);

    return 0;
}
